/*
 * TraceNStepSCAN.c
 *
 *  Created on: 25/11/2011
 *      Author: utn_so
 */

#include "libPPD.h"
#include "N-Step-SCAN.h"

void informacionNStepSCAN (int32_t nroSector, char **trace)
{
	extern pthread_mutex_t bloqueaLista;
	extern t_config config;
	extern tCabezal cabezal;
	extern t_log *loguear;

	int32_t tamanioLista = 0; int32_t cantSectoresRecorridos = 0;
	int32_t bloquearLista = 0;
	int32_t cantSaltosEntrePistas = 0; int32_t hayProxSector = 1;
	int32_t hayMuchasPistas = 0;  int32_t hayMuchosSectores = 0;
	int32_t hayMuchosPedidos = 0;
	float tiempoSector, tiempoConsumido;
	int32_t tamanioMemoria;
	uint32_t posicionCabezal;
	char *sectoresCHS = NULL;
	char *sectoresRecorridos = NULL;
	char *pistaSector = NULL;
	char *ultimaPista = NULL;
	char *ultimoSector = NULL;
	t_CHS sectorCHS, sectorPedidoCHS, proxSectorCHS, posicionCabezalCHS;

	tamanioMemoria = (sizeof(uint32_t)*2) +2;            //dos uint uno para c otro para s + el espacio + los dos puntos.
	sectoresCHS = (char*) calloc (25, tamanioMemoria);
	pistaSector = (char *) calloc(1, tamanioMemoria + 4);
	ultimoSector = (char *) calloc(1, tamanioMemoria + 4); //puntos suspensivos

	pasarACHS (nroSector, &sectorPedidoCHS);

	//Armo cola de pedidos y guardo el tamaño y el próximo sector

	bloquearLista =  pthread_mutex_lock(&bloqueaLista);
	if (strcmp(config.modoInicio, "CONNECT") == 0)
	{
		extern t_listaPRAID *listaPedidosPRAID;
		t_nodoPRAID * nodo;
		nodo = listaPedidosPRAID->head;

		sprintf(pistaSector, "%d:%d ", sectorPedidoCHS.C, sectorPedidoCHS.S);
		strcat(sectoresCHS, pistaSector);

		while (nodo != NULL)
		{
			pasarACHS (nodo->paquete.nroSector , &sectorCHS);
			sprintf(pistaSector, "%d:%d ", sectorCHS.C, sectorCHS.S);
			if(tamanioLista == 0) //guardo el primer sector como próximo sector
			{
				proxSectorCHS.C = sectorCHS.C;
				proxSectorCHS.S = sectorCHS.S;
				hayProxSector = 0;
			}
			if (tamanioLista < 20)
			{
				strcat(sectoresCHS, pistaSector);
			}
			else
			{
				hayMuchosPedidos = 1;
				sprintf(ultimoSector, "... %d:%d", sectorCHS.C, sectorCHS.S);
			}
			tamanioLista++;
			nodo = nodo->next;
		}
		tamanioLista++;
		if (hayMuchosPedidos == 1)
			strcat(sectoresCHS, ultimoSector);
	}
	else if (strcmp(config.modoInicio, "LISTEN") == 0)
	{
		extern t_listaPFS *listaPedidosPFS;
		t_nodoPFS * nodo;
		nodo = listaPedidosPFS->head;

		sprintf(pistaSector, "%d:%d ", sectorPedidoCHS.C, sectorPedidoCHS.S);
		strcat(sectoresCHS, pistaSector);

		while (nodo != NULL)
		{
			pasarACHS (nodo->paquete.nroSector, &sectorCHS);
			sprintf(pistaSector, "%d:%d ", sectorCHS.C, sectorCHS.S);
			if(tamanioLista == 0) //guardo el primer sector como próximo sector
			{
				proxSectorCHS.C = sectorCHS.C;
				proxSectorCHS.S = sectorCHS.S;
				hayProxSector = 0;
			}
			if (tamanioLista < 20)
			{
				strcat(sectoresCHS, pistaSector);
			}
			else
			{
				hayMuchosPedidos = 1;
				sprintf(ultimoSector, "... %d:%d", sectorCHS.C, sectorCHS.S);
			}
			tamanioLista++;
			nodo = nodo->next;
		}
		tamanioLista++;
		if (hayMuchosPedidos == 1)
			strcat(sectoresCHS, ultimoSector);
	}

	bloquearLista =  pthread_mutex_unlock(&bloqueaLista);

	// Armo los sectores recorridos desde la Posición Actual hasta el Sector Pedido

	sectoresRecorridos = (char*) calloc (30, tamanioMemoria);
	ultimaPista = (char *) calloc(1, tamanioMemoria + 4);

	pasarAuint(cabezal.posActual, &posicionCabezal);
	sprintf(pistaSector, "%d:%d ", cabezal.posActual.C, cabezal.posActual.S);
	strcat(sectoresRecorridos, pistaSector);

	t_CHS extremoSuperior;
	t_CHS extremoInferior;

	extremoSuperior.C = config.c-1;
	extremoInferior.C = 0;

	while (posicionCabezal != nroSector)
	{
		pasarACHS (posicionCabezal, &posicionCabezalCHS);

		if (posicionCabezalCHS.C == sectorPedidoCHS.C)
		{
			// recorrer sectores de la pista
			if (cantSectoresRecorridos == 0)
				cantSectoresRecorridos ++;   //porque cuenta en donde estaba, en los otros casos no porque lo saltea.
			if(hayMuchasPistas == 1)
			{
				strcat(sectoresRecorridos, ultimaPista);
				hayMuchasPistas = 0;
			}
			if (posicionCabezalCHS.S == (config.s-1))// lo vuelve a cero si es el ultimo sector
			{
				posicionCabezalCHS.S = 0;
				pasarAuint(posicionCabezalCHS, &posicionCabezal);
			}
			else
			{
				posicionCabezalCHS.S++;
				pasarAuint(posicionCabezalCHS, &posicionCabezal);
				cantSectoresRecorridos++;
			}
			if (cantSectoresRecorridos < 10)
			{
				sprintf(pistaSector, "%d:%d ", posicionCabezalCHS.C, posicionCabezalCHS.S);
				strcat(sectoresRecorridos, pistaSector);
			}
			else
			{
				hayMuchosSectores = 1;
				sprintf(ultimoSector, "... %d:%d", posicionCabezalCHS.C, posicionCabezalCHS.S);
			}
		}

		if (cabezal.sentido == ASCENDENTE)
		{
			if (posicionCabezalCHS.C < sectorPedidoCHS.C)
			{
				// saltar pistas de forma creciente

				posicionCabezalCHS.C++;
				sprintf(pistaSector, "%d:%d ", posicionCabezalCHS.C, posicionCabezalCHS.S);
				pasarAuint(posicionCabezalCHS, &posicionCabezal);

				if(cantSaltosEntrePistas < 10)
					strcat(sectoresRecorridos, pistaSector);
				else
				{
					hayMuchasPistas = 1;
					sprintf (ultimaPista, "... %d:%d ", posicionCabezalCHS.C, posicionCabezalCHS.S);
				}
				cantSaltosEntrePistas++;
			}
			else if(posicionCabezalCHS.C > sectorPedidoCHS.C)
			{
				// llegar al extremo superior saltando pistas cambiar a DESCENDENTE y empieza a saltar pistas
				// me fijo si esta en el extremo superior, si esta lo cambio para descencente,
				// si no esta salto pistas hasta llegar y despues cambio el sentido
				if (posicionCabezalCHS.C == extremoSuperior.C-2 && cantSaltosEntrePistas > 2)
				{
					posicionCabezalCHS.C++;
					sprintf (pistaSector, "... %d:%d ", posicionCabezalCHS.C, posicionCabezalCHS.S);
					pasarAuint(posicionCabezalCHS, &posicionCabezal);
					strcat(sectoresRecorridos, pistaSector);
					cantSaltosEntrePistas++;

					posicionCabezalCHS.C++;
					sprintf (pistaSector, "%d:%d ", posicionCabezalCHS.C, posicionCabezalCHS.S);
					pasarAuint(posicionCabezalCHS, &posicionCabezal);
					strcat(sectoresRecorridos, pistaSector);
					cantSaltosEntrePistas++;

				}


				else if (posicionCabezalCHS.C == extremoSuperior.C && cabezal.sentido == ASCENDENTE)
				{
					cabezal.sentido = DESCENDENTE;
					pasarAuint(posicionCabezalCHS, &posicionCabezal);

					// salta pistas en forma decreciente

					posicionCabezalCHS.C--;

					sprintf(pistaSector, "%d:%d ", posicionCabezalCHS.C, posicionCabezalCHS.S);
					pasarAuint(posicionCabezalCHS, &posicionCabezal);

					strcat(sectoresRecorridos, pistaSector);

					cantSaltosEntrePistas++;
				}
				else if (posicionCabezalCHS.C < extremoSuperior.C)
				{
					// saltar pistas de forma creciente
					posicionCabezalCHS.C++;
					sprintf(pistaSector, "%d:%d ", posicionCabezalCHS.C, posicionCabezalCHS.S);
					pasarAuint(posicionCabezalCHS, &posicionCabezal);

					if(cantSaltosEntrePistas < 10)
						strcat(sectoresRecorridos, pistaSector);
					else
					{
						hayMuchasPistas = 1;
						sprintf (ultimaPista, "... %d:%d ", posicionCabezalCHS.C, posicionCabezalCHS.S);
					}
					cantSaltosEntrePistas++;
				}
			}
		}
		else if (cabezal.sentido == DESCENDENTE)
		{
			if (posicionCabezalCHS.C > sectorPedidoCHS.C)
			{
				// saltar pistas de forma decreciente
				posicionCabezalCHS.C--;

				sprintf(pistaSector, "%d:%d ", posicionCabezalCHS.C, posicionCabezalCHS.S);
				pasarAuint(posicionCabezalCHS, &posicionCabezal);

				if(cantSaltosEntrePistas < 10)
					strcat(sectoresRecorridos, pistaSector);
				else
				{
					hayMuchasPistas = 1;
					sprintf (ultimaPista, "... %d:%d ", posicionCabezalCHS.C, posicionCabezalCHS.S);
				}
				cantSaltosEntrePistas++;
			}
			else if (posicionCabezalCHS.C < sectorPedidoCHS.C)
			{
				// llegar al extremo inferior saltando pistas y cambiar a ASCENDENTE y empieza a saltar pistas

				if (posicionCabezalCHS.C == extremoInferior.C+2 && cantSaltosEntrePistas > 2)
				{
					posicionCabezalCHS.C--;
					sprintf (pistaSector, "... %d:%d ", posicionCabezalCHS.C, posicionCabezalCHS.S);
					pasarAuint(posicionCabezalCHS, &posicionCabezal);

					strcat(sectoresRecorridos, pistaSector);

					cantSaltosEntrePistas++;

					posicionCabezalCHS.C--;
					sprintf (pistaSector, "%d:%d ", posicionCabezalCHS.C, posicionCabezalCHS.S);
					pasarAuint(posicionCabezalCHS, &posicionCabezal);

					strcat(sectoresRecorridos, pistaSector);

					cantSaltosEntrePistas++;
				}

				else if (posicionCabezalCHS.C == extremoInferior.C && cabezal.sentido == DESCENDENTE)
				{
					cabezal.sentido = ASCENDENTE;
					pasarAuint(posicionCabezalCHS, &posicionCabezal);

					// salta pistas en forma creciente
					posicionCabezalCHS.C++;

					sprintf(pistaSector, "%d:%d ", posicionCabezalCHS.C, posicionCabezalCHS.S);
					pasarAuint(posicionCabezalCHS, &posicionCabezal);

					strcat(sectoresRecorridos, pistaSector);

					cantSaltosEntrePistas++;
				}
				else if (posicionCabezalCHS.C > extremoInferior.C)
				{
					// saltar pistas de forma decreciente
					posicionCabezalCHS.C--;
					sprintf(pistaSector, "%d:%d ", posicionCabezalCHS.C, posicionCabezalCHS.S);
					pasarAuint(posicionCabezalCHS, &posicionCabezal);

					if(cantSaltosEntrePistas < 10)
						strcat(sectoresRecorridos, pistaSector);
					else
					{
						hayMuchasPistas = 1;
						sprintf (ultimaPista, "... %d:%d ", posicionCabezalCHS.C, posicionCabezalCHS.S);
					}
				cantSaltosEntrePistas++;
				}
			}
		}
	}
	if (hayMuchosSectores == 1)
		strcat(sectoresRecorridos, ultimoSector);
	if (hayMuchasPistas == 1)
		strcat(sectoresRecorridos, ultimaPista);

	tiempoSector = (float)(60000/config.rpm);         //en ms.
	tiempoSector = (float)(tiempoSector/config.s);
	tiempoConsumido = config.tiempoSaltoPistas *cantSaltosEntrePistas + tiempoSector * cantSectoresRecorridos;

	if(config.logActivado == 1)
	{
		if (hayProxSector == 1)
			log_info (loguear, "PPD", "\nCola de Pedidos: %s\nTamaño: %d\nPosicion Actual: %d:%d\nSector Solicitado: %d:%d\n"
					"Sectores Recorridos: %s\nTiempo Consumido: %f ms\nProximo Sector: -\n\n", sectoresCHS, tamanioLista,
					cabezal.posActual.C, cabezal.posActual.S, sectorPedidoCHS.C, sectorPedidoCHS.S, sectoresRecorridos,
					tiempoConsumido);
		else
			log_info (loguear, "PPD", "\nCola de Pedidos: %s\nTamaño: %d\nPosicion Actual: %d:%d\nSector Solicitado: %d:%d\n"
					"Sectores Recorridos: %s\nTiempo Consumido: %f ms\nProximo Sector: %d:%d\n\n", sectoresCHS, tamanioLista,
					cabezal.posActual.C, cabezal.posActual.S, sectorPedidoCHS.C, sectorPedidoCHS.S, sectoresRecorridos,
					tiempoConsumido, proxSectorCHS.C, proxSectorCHS.S);
	}
	if(trace != NULL)
	{
		if (hayProxSector == 1)
			sprintf(*trace, "%d:%d\n%d:%d\n%s\n%f\n-:-\n", cabezal.posActual.C, cabezal.posActual.S, sectorPedidoCHS.C,
					sectorPedidoCHS.S, sectoresRecorridos,tiempoConsumido);
		else
			sprintf(*trace, "%d:%d\n%d:%d\n%s\n%f\n%d:%d\n", cabezal.posActual.C, cabezal.posActual.S, sectorPedidoCHS.C,
					sectorPedidoCHS.S, sectoresRecorridos,tiempoConsumido, proxSectorCHS.C, proxSectorCHS.S);
	}

	free(sectoresCHS);
	free(sectoresRecorridos);
	free(pistaSector);
	free(ultimaPista);
	free(ultimoSector);
}


